#ifndef _BUFFER_H_
#define _BUFFER_H_






namespace sd
{
namespace tools
{
namespace buffer
{

/// TODO CHANGES!!!!!
class Buffer
{
public:
	size_t reserv()const{ return reserv_; }
	size_t size()const{ return size_; }
	const void *begin()const{ return ptr_; }
	const void *end()const{ return (const char*)ptr_+size(); }
	void resize( size_t newSize );
	void clear(){ resize(0); }
	void source( const Buffer& ref );
	void add( const Buffer& ref );

	virtual void realloc( size_t newSize )=0;

	template< typename T >
	T& cast( size_t index = 0 );

	template< typename T >
	const T& cast( size_t index = 0 )const;

	//char& operator[]( size_t index ){ return cast<char>( index ); }
	const char& operator[]( size_t index )const{ return cast<const char>( index ); }

	Buffer& operator+=( const Buffer& ref );
	Buffer& operator=( const Buffer& ref );
	bool operator==( const Buffer& ref )const;
	bool operator!=( const Buffer& ref )const{ return !(*this==ref); }

protected:
	Buffer():ptr_(0), size_(0),reserv_(0){}
	Buffer( const void* ptr, size_t size, size_t reserv ):
		ptr_(ptr), size_(size), reserv_(reserv){}
	
	const void* ptr_;
	size_t size_, reserv_;
};

template< int BufferSize, typename T = char >
class StaticBuffer: public Buffer
{
public:
	StaticBuffer( const Buffer& ref ): Buffer( &buffer_, 0, BufferSize ){ source( ref ); }
	StaticBuffer(): Buffer( &buffer_, 0, BufferSize ){}
private:
	virtual void realloc( size_t s );
	T buffer_[ BufferSize ];
};


class DynamicBuffer: public Buffer
{
public:
	DynamicBuffer(){}
	DynamicBuffer( const Buffer& ref ):Buffer( 0, 0, 0 ){ source( ref ); }
	DynamicBuffer( size_t size ){ realloc( size ); }
private:
	virtual void realloc( size_t newAllocSize );
};


class PtrBuffer: public Buffer
{
public:
	PtrBuffer( const void* ptr, size_t size ): Buffer( ptr, size, size ){}
	PtrBuffer( const Buffer& ref ): Buffer( ref.begin(), ref.size(), ref.size() ){}
	void reset( const Buffer& ref );

private:
	virtual void realloc( size_t s );
};




template< typename T >
PtrBuffer MakeBuffer( const T& obj ){ return PtrBuffer( static_cast<const void*>(&obj), sizeof( obj ) ); }

}//namespace buffer
}//namespace tools
}//namespace sd

#define _BUFFER_HPP_
#include "Buffer.hpp"
#undef _BUFFER_HPP_


#endif//_BUFFER_H_